package com.example.springboot.service.impl;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.springboot.config.schedule.CacheManager;
import com.example.springboot.entity.MetAlarm;
import com.example.springboot.entity.ProductServer;
import com.example.springboot.entity.User;
import com.example.springboot.mapper.ProductServerMapper;
import com.example.springboot.mapper.UserMapper;
import com.example.springboot.service.IProductServerService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;

import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author dhn
 * @since 2024-04-15
 */
@Service
@RequiredArgsConstructor
public class ProductServerServiceImpl extends ServiceImpl<ProductServerMapper, ProductServer> implements IProductServerService {

    private final RestTemplate restTemplate;

    private final UserMapper userMapper;

    private final ProductServerMapper productServerMapper;


    @Value("${wx.mp.appid}")
    private String appid;

    @Value("${wx.mp.appSecret}")
    private String appSecret;

    @Value("${wx.mp.fileMonitorModelId}")
    private String fileMonitorModelId;

    @Override
    public void checkAndSendProductMessage() {

        LambdaQueryWrapper<ProductServer> queryWrapper = Wrappers.lambdaQuery(ProductServer.class)
                .eq(ProductServer::getIsFlag, "0");
        List<ProductServer> productServersList = baseMapper.selectList(queryWrapper);
        if (productServersList.size() != 0) {
            String accessToken = CacheManager.getAccessToken();
            LambdaQueryWrapper<User> userLambdaQueryWrapper = Wrappers.lambdaQuery(User.class)
                    .eq(User::getIsDisabled, "0");
//                    .eq(User::getIsFileSubscribe, "1");
            //获取所有用户
            List<User> userList = userMapper.selectList(userLambdaQueryWrapper);
            Set<ProductServer> productServerSet = new HashSet<>();
            userList.forEach(user->{
                if(user.getOpenid()!=null){
                    productServersList.forEach(productServer -> {
                        if(Objects.equals(user.getRole(), "ROLE_ADMIN")){
                            sendAlarmMsgToUser(accessToken,productServer,user);
                            productServerSet.add(productServer);
                        }
                        else if((Objects.equals(user.getRole(),"ROLE_FARM_USER")
                                ||Objects.equals(user.getRole(),"ROLE_JK_USER")
                                ||(Objects.equals(user.getRole(),"ROLE_DW_USER")&& Objects.equals(user.getRoleClass(), "1")))&& Objects.equals(productServer.getArea(), "hubei")){
                            sendAlarmMsgToUser(accessToken,productServer,user);
                            productServerSet.add(productServer);
                        }
                        else if((Objects.equals(user.getRole(),"ROLE_DW_USER")&& Objects.equals(user.getRoleClass(), "0"))&&Objects.equals(productServer.getArea(), "huazhong")){
                            sendAlarmMsgToUser(accessToken,productServer,user);
                            productServerSet.add(productServer);
                        }
                    });
                }
            });
            List<ProductServer> productServer = new ArrayList<>(productServerSet);
            if (productServer.size() != 0) {
                productServerMapper.updateBatchProductServerInfo(productServer);
            }
        }

    }

//    public String getAccessToken() {
//        String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appid, appSecret);
//        try {
//            String response = HttpUtil.get(url);
//            JSONObject jsonObject = JSONUtil.parseObj(response);
//            if (jsonObject.containsKey("access_token")) {
//                return jsonObject.getStr("access_token");
//            } else {
//                // 输出错误信息
//                System.out.println("Error getting access token: " + jsonObject.getStr("errmsg"));
//            }
//        } catch (Exception e) {
//            System.out.println("Error retrieving access token: " + e.getMessage());
//        }
//        return null;
//    }

    public void sendAlarmMsgToUser(String accessToken, ProductServer productServer, User user) {
        int retryCount = 0;
        while (retryCount < 2) {  // 允许一次重试
            try {
                String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                Date date = new Date();
                String pubTime = sdf.format(date);
                Map<String, Map<String, String>> data = buildMessageData(productServer.getFileName(), pubTime);

                Map<String, Object> body = new HashMap<>();
                body.put("touser", user.getOpenid());
                body.put("template_id", fileMonitorModelId);
                body.put("data", data);
                String encodedUrl = URLEncoder.encode(productServer.getFullUrl(), "UTF-8");
//                String page = "pages/weather/detail/detail?type=2&pdfUrl=" + encodedUrl;
                String page = "pages/pdfDetail?type=2&pdfUrl=" + encodedUrl;
                body.put("page", page);
                body.put("miniprogram_state", "formal");

                HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
                ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
                if (response.getStatusCode() == HttpStatus.OK) {
                    Map<String, Object> responseMap = JSONUtil.toBean(response.getBody(), Map.class);
                    if (responseMap.containsKey("errcode") && (Integer) responseMap.get("errcode") != 0) {
                        Integer errCode = (Integer) responseMap.get("errcode");
                        if (errCode == 40001 || errCode == 42001) { // Token expired
                            accessToken = CacheManager.refreshAccessToken(); // Refresh token
                            retryCount++;
                            continue;
                        } else if (errCode == 40003 || errCode == 43101) { // Handle specific WeChat errors
                            handleWechatResponse(responseMap, user);
                            break;
                        }
                        System.out.println("errorCode:"+responseMap.get("errcode"));
                    }
                    System.out.println("Message sent successfully.");
                    break;
                } else {
                    System.out.println("Failed to send message: HTTP status " + response.getStatusCode());
                    break;
                }
            } catch (HttpClientErrorException | HttpServerErrorException e) {
                System.err.println("HTTP error occurred: " + e.getStatusCode() + " " + e.getResponseBodyAsString());
                break;
            } catch (Exception e) {
                System.err.println("An error occurred: " + e.getMessage());
                break;
            }
        }
    }


    private void handleWechatResponse(Map<String, Object> responseMap, User user) {
        if (responseMap.containsKey("errcode") && !responseMap.get("errcode").equals(0)) {
            Integer errCode = (Integer) responseMap.get("errcode");
            String errMsg = (String) responseMap.get("errmsg");
            switch (errCode) {
                // 添加更多错误处理案例
                case 40003:
                    System.err.println("Invalid openid, check the provided openid: " + errMsg);
//                    if (user.getIsSubscribe() != null && user.getIsSubscribe().equals("1")) {
//                        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class)
//                                .eq(User::getId, user.getId())
//                                .set(User::getIsFileSubscribe, "0");
//                        userMapper.update(null, updateWrapper);
//                    }
                    break;
                case 43101:
                    System.err.println("Invalid openid, check the provided openid: " + errMsg);
//                    if (user.getIsSubscribe() != null && user.getIsSubscribe().equals("1")) {
//                        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class)
//                                .eq(User::getId, user.getId())
//                                .set(User::getIsFileSubscribe, "0");
//                        userMapper.update(null, updateWrapper);
//                    }
                    break;
                default:
//                    System.err.println("Invalid openid, check the provided openid: " + errMsg);
//                    if (user.getIsSubscribe() != null && user.getIsSubscribe().equals("1")) {
//                        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class)
//                                .eq(User::getId, user.getId())
//                                .set(User::getIsFileSubscribe, "0");
//                        userMapper.update(null, updateWrapper);
//                    }
                    break;
            }
        } else {
            System.out.println("Message sent successfully.");
        }
    }

    private Map<String, Map<String, String>> buildMessageData(String fileName, String pubTime) {
        Map<String, Map<String, String>> data = new HashMap<>();
        data.put("thing1", createDataItem(fileName));
        data.put("date3", createDataItem(pubTime));
        return data;
    }

    private Map<String, String> createDataItem(String value) {
        Map<String, String> item = new HashMap<>();
        item.put("value", value);
        return item;
    }

}
